package sany.iec.service.svg02;

import com.serotonin.modbus4j.BasicProcessImage;
import com.serotonin.modbus4j.ModbusSlaveSet;
import com.serotonin.modbus4j.ProcessImage;
import com.serotonin.modbus4j.ProcessImageListener;
import com.serotonin.modbus4j.exception.IllegalDataAddressException;
import com.serotonin.modbus4j.exception.ModbusInitException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import sany.iec.config.ModbusSVG02Server;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

/**
 * @Author : 托马斯
 * @Date : 2025/7/3 10:31
 * @Description :
 */
@Service
@Slf4j
public class Svg02DataService {

    @Resource
    private ModbusSVG02Server modbusSVG02Server;

    @Value("${modbus.svg02.id}")
    private int id;

    @Resource(name = "modbus-svg02")
    private ModbusSlaveSet modbusSlaveSet;

    @PostConstruct
    public void init() throws ModbusInitException {
        //向过程影像区添加数据
        modbusSlaveSet.addProcessImage(getModscanProcessImage(id));
        new Thread(() -> {
            try {
                modbusSlaveSet.start();
            } catch (ModbusInitException e) {
                log.error("Modbus init error", e);
            }
        }).start();
        log.info("Modbus init success SVG02, port: {}  id: {}", modbusSVG02Server.getPort(), id);
    }

    private BasicProcessImage getModscanProcessImage(int slaveId) {
        /* 初始化过程影像区 */
        BasicProcessImage processImage = new BasicProcessImage(slaveId);
        /* 设置无效地址的默认值为Short类型的最大值 */
        // processImage.setInvalidAddressValue(Short.MAX_VALUE);

        /* 初始化过程影像区各个数值为0 */
        for (int i = 0; i < 10000; i++) {
            processImage.setCoil(i, Math.random() > 0.5);
            processImage.setInput(i, Math.random() > 0.5);
            processImage.setHoldingRegister(i, (short) (Math.random() * 100));
            processImage.setInputRegister(i, (short) (Math.random() * 100));
        }
        /* 为影像区添加监听 */
        processImage.addListener(new BasicProcessImageListener());
        return processImage;
    }

    private static class BasicProcessImageListener implements ProcessImageListener {

        @Override
        public void coilWrite(int i, boolean b, boolean b1) {

        }

        @Override
        public void holdingRegisterWrite(int offset, short oldValue, short newValue) {
            log.info("Register at " + offset + "," + "change " + oldValue + " to " + newValue);
        }
    }

    public void setHoldingRegister(int i, short newValue) {
        ProcessImage processImage = modbusSlaveSet.getProcessImage(id);
        processImage.setHoldingRegister(i, newValue);
    }

    public Short getHoldingRegister(int i) throws IllegalDataAddressException {
        ProcessImage processImage = modbusSlaveSet.getProcessImage(id);
        return processImage.getHoldingRegister(i);
    }

}
